#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
问卷生成工具 - Excel转JSON转换器
支持从Excel文件生成符合系统格式的问卷JSON文件
"""

import pandas as pd
import json
import os
import sys
from typing import Dict, List, Any, Optional
import argparse


class QuestionnaireConverter:
    """问卷转换器类"""
    
    def __init__(self):
        self.question_types = {
            'tf': 'true_false',
            'choice': 'multiple_choice', 
            'plain': 'explanatory_text'
        }
        
    def load_excel(self, file_path: str) -> Dict[str, pd.DataFrame]:
        """加载Excel文件，返回所有工作表的数据"""
        try:
            excel_file = pd.ExcelFile(file_path)
            sheets = {}
            for sheet_name in excel_file.sheet_names:
                sheets[sheet_name] = pd.read_excel(file_path, sheet_name=sheet_name)
            return sheets
        except Exception as e:
            raise Exception(f"加载Excel文件失败: {str(e)}")
    
    def validate_questions_sheet(self, df: pd.DataFrame) -> None:
        """验证问题工作表格式"""
        required_columns = [
            'id', 'number', 'content', 'type', 'score_id'
        ]
        
        missing_columns = [col for col in required_columns if col not in df.columns]
        if missing_columns:
            raise ValueError(f"问题工作表缺少必需列: {missing_columns}")
        
        # 验证问题类型
        valid_types = ['tf', 'choice', 'plain']
        invalid_types = df[~df['type'].isin(valid_types)]['type'].unique()
        if len(invalid_types) > 0:
            raise ValueError(f"无效的问题类型: {invalid_types}. 有效类型: {valid_types}")
    
    def validate_score_judge_sheet(self, df: pd.DataFrame) -> None:
        """验证评分规则工作表格式"""
        required_columns = ['id', 'name', 'threshold', 'assessment']
        missing_columns = [col for col in required_columns if col not in df.columns]
        if missing_columns:
            raise ValueError(f"评分规则工作表缺少必需列: {missing_columns}")
    
    def process_questions(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
        """处理问题数据"""
        questions = []
        
        for _, row in df.iterrows():
            question = {
                "id": int(row['id']),
                "number": int(row['number']) if pd.notna(row['number']) else -1,
                "content": str(row['content']),
                "type": str(row['type'])
            }
            
            # 处理评分信息
            if pd.notna(row['score_id']):
                scores = []
                if pd.notna(row['scores']):
                    scores = [float(x) for x in str(row['scores']).split(',')]
                else:
                    # 根据问题类型设置默认分数
                    if question['type'] == 'tf':
                        scores = [1, 0]
                    elif question['type'] == 'choice':
                        # 需要根据选项数量设置分数
                        if pd.notna(row['options']):
                            option_count = len(str(row['options']).split('|'))
                            scores = [0] * option_count
                            if pd.notna(row['correct_answer']):
                                correct_idx = int(row['correct_answer'])
                                if 0 <= correct_idx < len(scores):
                                    scores[correct_idx] = 1
                
                question["judge"] = {
                    "scores": scores,
                    "score_id": str(row['score_id'])
                }
            
            # 处理选项（选择题）
            if question['type'] == 'choice' and pd.notna(row['options']):
                question["options"] = [opt.strip() for opt in str(row['options']).split('|')]
            
            # 处理判断题选项
            if question['type'] == 'tf' and pd.notna(row['tf_options']):
                question["tf_options"] = [opt.strip() for opt in str(row['tf_options']).split('|')]
            
            # 处理特殊属性
            if pd.notna(row['special']):
                special_config = str(row['special']).strip()
                if special_config:
                    try:
                        question["special"] = json.loads(special_config)
                    except json.JSONDecodeError:
                        # 简单处理图片类型
                        if special_config.startswith('image:'):
                            image_url = special_config.replace('image:', '').strip()
                            question["special"] = [{"type": "image", "args": {"url": image_url}}]
            
            # 处理前置条件
            if pd.notna(row['prerequisite']):
                prereq_config = str(row['prerequisite']).strip()
                if prereq_config:
                    try:
                        question["prerequisite"] = json.loads(prereq_config)
                    except json.JSONDecodeError:
                        # 简单处理前置条件
                        if '|' in prereq_config:
                            parts = prereq_config.split('|')
                            if len(parts) >= 2:
                                question["prerequisite"] = [{
                                    "type": "answer",
                                    "args": {
                                        "id": int(parts[0]),
                                        "value": parts[1]
                                    }
                                }]
            
            # 处理头部类型
            if pd.notna(row['header']):
                question["header"] = str(row['header'])
            
            questions.append(question)
        
        return questions
    
    def process_score_judge(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
        """处理评分规则数据"""
        score_judges = []
        
        for _, row in df.iterrows():
            score_judge = {
                "id": str(row['id']),
                "name": str(row['name']),
                "threshold": float(row['threshold']) if pd.notna(row['threshold']) else 0,
                "assessment": str(row['assessment'])
            }
            
            # 处理结果描述
            if pd.notna(row['results']):
                results = [r.strip() for r in str(row['results']).split('|')]
                score_judge["results"] = results
            
            # 处理图标URL
            if pd.notna(row['icon_url']):
                score_judge["iconUrl"] = str(row['icon_url'])
            
            # 处理评分区间
            if pd.notna(row['intervals']):
                try:
                    intervals_config = str(row['intervals']).strip()
                    if intervals_config:
                        score_judge["intervals"] = json.loads(intervals_config)
                except json.JSONDecodeError:
                    pass
            
            score_judges.append(score_judge)
        
        return score_judges
    
    def process_slice(self, df: pd.DataFrame) -> List[List[int]]:
        """处理切片数据"""
        if df.empty:
            return []
        
        slices = []
        for _, row in df.iterrows():
            if pd.notna(row['question_ids']):
                question_ids = [int(x) for x in str(row['question_ids']).split(',')]
                slices.append(question_ids)
        
        return slices
    
    def convert_excel_to_json(self, excel_path: str, output_path: str = None) -> str:
        """将Excel文件转换为JSON格式的问卷"""
        try:
            # 加载Excel文件
            sheets = self.load_excel(excel_path)
            
            # 检查必需的工作表
            if 'questionnaire_info' not in sheets:
                raise ValueError("缺少 'questionnaire_info' 工作表")
            if 'questions' not in sheets:
                raise ValueError("缺少 'questions' 工作表")
            
            # 处理问卷基本信息
            info_df = sheets['questionnaire_info']
            questionnaire = {
                "title": str(info_df.iloc[0]['title']),
                "result_page": str(info_df.iloc[0]['result_page']) if pd.notna(info_df.iloc[0]['result_page']) else "$back"
            }
            
            # 处理问题
            questions_df = sheets['questions']
            self.validate_questions_sheet(questions_df)
            questionnaire["questions"] = self.process_questions(questions_df)
            
            # 处理切片
            if 'slice' in sheets:
                slice_df = sheets['slice']
                questionnaire["slice"] = self.process_slice(slice_df)
            
            # 处理评分规则
            if 'score_judge' in sheets:
                score_judge_df = sheets['score_judge']
                self.validate_score_judge_sheet(score_judge_df)
                questionnaire["score_judge"] = self.process_score_judge(score_judge_df)
            
            # 处理评分配置
            if 'score_figure' in sheets:
                score_figure_df = sheets['score_figure']
                if not score_figure_df.empty:
                    questionnaire["score_figure"] = {
                        "max": int(score_figure_df.iloc[0]['max']) if pd.notna(score_figure_df.iloc[0]['max']) else 100,
                        "reverse": bool(score_figure_df.iloc[0]['reverse']) if pd.notna(score_figure_df.iloc[0]['reverse']) else False
                    }
            
            # 处理TF选项（全局）
            if 'tf_options' in sheets:
                tf_options_df = sheets['tf_options']
                if not tf_options_df.empty:
                    questionnaire["tf_options"] = [str(opt) for opt in tf_options_df['option'].tolist()]
            
            # 生成输出文件路径
            if output_path is None:
                base_name = os.path.splitext(os.path.basename(excel_path))[0]
                output_path = os.path.join(os.path.dirname(excel_path), f"{base_name}.json")
            
            # 保存JSON文件
            with open(output_path, 'w', encoding='utf-8') as f:
                json.dump(questionnaire, f, ensure_ascii=False, indent=2)
            
            return output_path
            
        except Exception as e:
            raise Exception(f"转换失败: {str(e)}")


def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='Excel问卷转JSON工具')
    parser.add_argument('input', help='输入的Excel文件路径')
    parser.add_argument('-o', '--output', help='输出的JSON文件路径（可选）')
    parser.add_argument('-v', '--verbose', action='store_true', help='显示详细信息')
    
    args = parser.parse_args()
    
    try:
        converter = QuestionnaireConverter()
        output_path = converter.convert_excel_to_json(args.input, args.output)
        
        print(f"转换成功！输出文件: {output_path}")
        
        if args.verbose:
            with open(output_path, 'r', encoding='utf-8') as f:
                data = json.load(f)
                print(f"问卷标题: {data['title']}")
                print(f"问题数量: {len(data['questions'])}")
                if 'score_judge' in data:
                    print(f"评分规则数量: {len(data['score_judge'])}")
    
    except Exception as e:
        print(f"错误: {str(e)}", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()

